import gateway from "./circle-gateway.js";
import { buildUrl, getData } from "./circle-common.js";

/// <reference path="./circle-types.js" />

/**
 * get block hash list by base height.
 * @param {number} baseHeight - the start height.
 * @returns {Promise<StringArrayResponse>} - the block hash list response.
 */
export async function getBlockHashList(baseHeight) {
  const url = buildUrl(gateway.block.path.blockchainHashListPath, {
    baseHeight
  });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * get block data hex string.
 * @param {string} hash - hash string
 * @returns {Promise<StringResponse>} - the get block data response.
 */
export async function getBlockData(hash) {
  const url = buildUrl(gateway.block.path.blockchainDataPath, { hash });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} BlockHeaderPO
 * @property {string} hash - block hash
 * @property {number} minedTimestamp - the mined timestamp.
 * @property {string} version - the block version
 * @property {number} height - the block height
 * @property {string} prevBlockHash - the previous block hash
 * @property {string} markleTreeRoot - the markle tree root hash
 * @property {string} [minerIpPort] - the miner ipPort
 * @property {string} [minerInfo] - the miner info
 * @property {number} difficulty - the block difficulty
 * @property {number} nonce - the nonce of the block
 */

/**
 * @typedef {Object} BlockPO
 * @property {BlockHeaderPO} header - the block header
 * @property {string} dataHexStr - the block content data hex string.
 */

/**
 * @typedef {Object} BlockResponse
 * @property {status} number - the response status
 * @property {string} message - the response message.
 * @property {BlockPO} data - the block data.
 */

/**
 * get block by block hash
 * @param {string} hash - the block hash
 * @returns {Promise<BlockResponse>} - the get block response.
 */
export async function getBlock(hash) {
  const url = buildUrl(gateway.block.path.blockchainPath, { hash });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} BlockHeaderListResponse
 * @property {status} number - the response status
 * @property {string} message - the response message.
 * @property {BlockHeaderPO[]} data - the block header array data.
 */

/**
 * get block header list by baseHeight
 * @param {number} baseHeight - the start height.
 * @returns {Promise<BlockHeaderListResponse>} - the result.
 */
export async function getBlockHeaderList(baseHeight) {
  const url = buildUrl(gateway.block.path.blockchainHeaderListPath, {
    baseHeight
  });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * get block tails hash list by baseHeight
 * @param {number} baseHeight - the base height.
 * @returns {Promise<StringArrayResponse>} - the get block tails hash list response.
 */
export async function getBlockTailsHashList(baseHeight) {
  const url = buildUrl(gateway.block.path.blockchainTailsHashListPath, {
    baseHeight
  });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} BlockTailsPO
 * @property {number} id - the id
 * @property {number} height - the block height
 * @property {string} hash - the block hash
 * @property {number} hashCrc32 - hash crc32
 * @property {string} prevHash - the block previous hash
 * @property {boolean} isMaster - if the block tail whether master.
 */

/**
 * @typedef {Object} BlockTailsResponse
 * @property {status} number - the response status
 * @property {string} message - the response message.
 * @property {BlockTailsResponse} data - the block header array data.
 */

/**
 * get block tails PO by hash
 * @param {string} hash - the block hash
 * @returns {Promise<BlockTailsResponse>} - the blocktails PO response
 */
export async function getBlockTailsPO(hash) {
  const url = buildUrl(gateway.block.path.blockchainTailsPOPath, { hash });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} TXInputPO
 * @property {string} txIdStr - transaction id string
 * @property {number} txOutputIndex - the transaction output index
 * @property {string} unlockScripts - the unlock scripts
 * @property {number} serialNO - the serial number.
 */

/**
 * @typedef {Object} TXOutputPO
 * @property {string} txIdStr - transaction id string
 * @property {number} idx - the transaction output index
 * @property {number} status - the transaction output status
 * @property {string} value - the output value
 * @property {string} lockScript - the lock script.
 */

/**
 * @typedef {Object} TransactionDetail
 * @property {string} blockHash - the block hash
 * @property {number} height - the block height
 * @property {string} txIdHexStr - transaction id hex string
 * @property {number} type - the transaction type
 * @property {TXInputPO[]} inputs - the input array
 * @property {TXOutputPO[]} outputs - the output array
 * @property {string[]} sendersPubKeyHash - the sender public key hashes
 * @property {string[]} receiversPubKeyHash - the receive public key hashes
 */

/**
 * @typedef {Object} TransactionDetailResponse
 * @property {number} status - the response status
 * @property {string} message - the response message
 * @property {TransactionDetail} data - the transaction detail data
 *
 */

/**
 * get Transaction by txId
 * @param {string} txId - the transaction id.
 * @returns {Promise<TransactionDetailResponse>} - the get transaction response.
 */
export async function getTxByTxId(txId) {
  const url = buildUrl(gateway.block.path.transactionByTxIdPath, { txId });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} TransactionDetailListResponse
 * @property {number} status - the response status
 * @property {string} message - the response message
 * @property {TransactionDetail[]} data - the transaction detail data
 *
 */

/**
 * search transaction by transaction id.
 * @param {string} txId - the transaction id
 * @returns {Promise<TransactionDetailListResponse>} - the search transaction response
 */
export async function searchTxByTxId(txId) {
  const url = buildUrl(gateway.block.path.searchTxByTxIdPath, { txId });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} AddressTxInfo
 * @property {string} address - the address
 * @property {string} pubKeyHash - the public key hash
 * @property {TransactionDetail[]} txDetailList - transaction detail list
 */

/**
 * @typedef {Object} AddressTxInfoResponse
 * @property {number} status - the response status
 * @property {string} message - the response message
 * @property {AddressTxInfo} data - the address transaction info data
 */

/**
 * search transaction by address
 * @param {string} address - the address
 * @param {string} minOutputKey - the minOutputKey
 * @param {number} limit - the page limit
 * @returns {Promise<AddressTxInfoResponse>} - the response
 */
export async function searchTxByAddress(address, minOutputKey, limit) {
  const url = buildUrl(gateway.block.path.searchTxByAddressPath, { address, minOutputKey, limit });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} AddressUTXOInfo
 * @property {string} address - the address
 * @property {string} pubKeyHash - the public key hash
 * @property {TXOutputPO[]} outputs - the unspent outputs
 */

/**
 * @typedef UTXOResponse
 * @property {number} status - the response status
 * @property {string} message - the response message
 * @property {AddressUTXOInfo[]} data - the address UTXO info data
 */

/**
 * search UTXO by address
 * @param {string} address - the address
 * @param {string} minOutputKey - the minOutputKey
 * @param {number} limit - the page limit
 * @returns {Promise<UTXOResponse>} - the response
 */
export async function searchUTXOs(address, minOutputKey, limit) {
  const url = buildUrl(gateway.block.path.searchUTXOsPath, { address, minOutputKey, limit });
  return getData(url, +gateway.http.timeoutRead);
}
